home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / uhitm.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  45KB  |  1,656 lines

  1. /*    SCCS Id: @(#)uhitm.c    3.1    92/12/10    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. static boolean FDECL(known_hitum, (struct monst *,int));
  8. static boolean FDECL(hitum, (struct monst *,int));
  9. #ifdef POLYSELF
  10. static int FDECL(explum, (struct monst *,struct attack *));
  11. static int FDECL(gulpum, (struct monst *,struct attack *));
  12. static boolean FDECL(hmonas, (struct monst *,int));
  13. #endif
  14. static void FDECL(nohandglow, (struct monst *));
  15.  
  16. extern boolean notonhead;    /* for long worms */
  17. /* The below might become a parameter instead if we use it a lot */
  18. static int dieroll;
  19.  
  20. struct monst *
  21. clone_mon(mon)
  22. struct monst *mon;
  23. {
  24.     coord mm;
  25.     struct monst *m2;
  26.  
  27.     mm.x = mon->mx;
  28.     mm.y = mon->my;
  29.     if (!enexto(&mm, mm.x, mm.y, mon->data)) return (struct monst *)0;
  30.     if (MON_AT(mm.x, mm.y) || mon->mhp <= 1) return (struct monst *)0;
  31.     /* may have been extinguished for population control */
  32.     if(mon->data->geno & G_EXTINCT) return((struct monst *) 0);
  33.     m2 = newmonst(0);
  34.     *m2 = *mon;            /* copy condition of old monster */
  35.     m2->nmon = fmon;
  36.     fmon = m2;
  37.     m2->m_id = flags.ident++;
  38.     m2->mx = mm.x;
  39.     m2->my = mm.y;
  40.  
  41.     m2->minvent = (struct obj *) 0; /* objects don't clone */
  42.     m2->mleashed = FALSE;
  43.     m2->mgold = 0L;
  44.     /* Max HP the same, but current HP halved for both.  The caller
  45.      * might want to override this by halving the max HP also.
  46.      */
  47.     m2->mhpmax = mon->mhpmax;
  48.     m2->mhp = mon->mhp /= 2;
  49.  
  50.     /* since shopkeepers and guards will only be cloned if they've been
  51.      * polymorphed away from their original forms, the clone doesn't have
  52.      * room for the extra information.  we also don't want two shopkeepers
  53.      * around for the same shop.
  54.      * similarly, clones of named monsters don't have room for the name,
  55.      * so we just make the clone unnamed instead of bothering to create
  56.      * a clone with room and copying over the name from the right place
  57.      * (which changes if the original was a shopkeeper or guard).
  58.      */
  59.     if (mon->isshk) m2->isshk = FALSE;
  60.     if (mon->isgd) m2->isgd = FALSE;
  61.     if (mon->ispriest) m2->ispriest = FALSE;
  62.     m2->mxlth = 0;
  63.     m2->mnamelth = 0;
  64.     place_monster(m2, m2->mx, m2->my);
  65.     newsym(m2->mx,m2->my);    /* display the new monster */
  66.     if (mon->mtame) {
  67.         struct monst *m3;
  68.  
  69.         /* because m2 is a copy of mon it is tame but not init'ed.
  70.          * however, tamedog will not re-tame a tame dog, so m2
  71.          * must be made non-tame to get initialized properly.
  72.          */
  73.         m2->mtame = 0;
  74.         if ((m3 = tamedog(m2, (struct obj *)0)) != 0)
  75.         m2 = m3;
  76.     }
  77.     return m2;
  78. }
  79.  
  80. boolean
  81. special_case(mtmp)
  82. /* Moved this code from attack() in order to     */
  83. /* avoid having to duplicate it in dokick.    */
  84. register struct monst *mtmp;
  85. {
  86.     char qbuf[QBUFSZ];
  87.  
  88.     if(mtmp->m_ap_type && !Protection_from_shape_changers
  89.                         && !sensemon(mtmp)) {
  90.         stumble_onto_mimic(mtmp);
  91.         mtmp->data->mflags3 &= ~M3_WAITMASK;
  92.         return(1);
  93.     }
  94.  
  95.     if(mtmp->mundetected && hides_under(mtmp->data) && !canseemon(mtmp)) {
  96.         mtmp->mundetected = 0;
  97.         if (!(Blind ? Telepat : (HTelepat & (W_ARMH|W_AMUL|W_ART)))) {
  98.             register struct obj *obj;
  99.  
  100.             if(Blind)
  101.                 pline("Wait!  There's a hidden monster there!");
  102.             else if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
  103.                 pline("Wait!  There's %s hiding under %s!",
  104.                     an(l_monnam(mtmp)), doname(obj));
  105.             wakeup(mtmp);
  106.             mtmp->data->mflags3 &= ~M3_WAITMASK;
  107.             return(TRUE);
  108.         }
  109.     }
  110.  
  111.     if (flags.confirm && mtmp->mpeaceful
  112.         && !Confusion && !Hallucination && !Stunned) {
  113.         /* Intelligent chaotic weapons (Stormbringer) want blood */
  114.         if (uwep && uwep->oartifact == ART_STORMBRINGER)
  115.             return(FALSE);
  116.  
  117.         if (canspotmon(mtmp)) {
  118.             Sprintf(qbuf, "Really attack %s?", mon_nam(mtmp));
  119.             if (yn(qbuf) != 'y') {
  120.                 flags.move = 0;
  121.                 mtmp->data->mflags3 &= ~M3_WAITMASK;
  122.                 return(TRUE);
  123.             }
  124.         }
  125.     }
  126.  
  127.     return(FALSE);
  128. }
  129.  
  130. schar
  131. find_roll_to_hit(mtmp)
  132. register struct monst *mtmp;
  133. {
  134.     schar tmp;
  135.     int tmp2;
  136.     struct permonst *mdat = mtmp->data;
  137.  
  138.     tmp = 1 + Luck + abon() +
  139.         find_mac(mtmp) +
  140. #ifdef POLYSELF
  141.         ((u.umonnum >= 0) ? uasmon->mlevel : u.ulevel);
  142. #else
  143.         u.ulevel;
  144. #endif
  145.  
  146. /*    it is unchivalrous to attack the defenseless or from behind */
  147.     if (pl_character[0] == 'K' && u.ualign.type == A_LAWFUL &&
  148.         (!mtmp->mcanmove || mtmp->msleep || mtmp->mflee) &&
  149.         u.ualign.record > -10) adjalign(-1);
  150.  
  151. /*    attacking peaceful creatures is bad for the samurai's giri */
  152.     if (pl_character[0] == 'S' && mtmp->mpeaceful &&
  153.         u.ualign.record > -10) adjalign(-1);
  154.  
  155. /*    Adjust vs. (and possibly modify) monster state.        */
  156.  
  157.     if(mtmp->mstun) tmp += 2;
  158.     if(mtmp->mflee) tmp += 2;
  159.  
  160.     if(mtmp->msleep) {
  161.         mtmp->msleep = 0;
  162.         tmp += 2;
  163.     }
  164.     if(!mtmp->mcanmove) {
  165.         tmp += 4;
  166.         if(!rn2(10)) {
  167.             mtmp->mcanmove = 1;
  168.             mtmp->mfrozen = 0;
  169.         }
  170.     }
  171.     if (is_orc(mtmp->data) && pl_character[0]=='E') tmp++;
  172.  
  173. /*    with a lot of luggage, your agility diminishes */
  174.     if(tmp2 = near_capacity()) tmp -= (tmp2*2) - 1;
  175.     if(u.utrap) tmp -= 3;
  176. #ifdef POLYSELF
  177. /*    Some monsters have a combination of weapon attacks and non-weapon
  178.  *    attacks.  It is therefore wrong to add hitval to tmp; we must add it
  179.  *    only for the specific attack (in hmonas()).
  180.  */
  181.     if(uwep && u.umonnum == -1) tmp += hitval(uwep, mdat);
  182. #else
  183.     if(uwep) tmp += hitval(uwep, mdat);
  184. #endif
  185.     return tmp;
  186. }
  187.  
  188. /* try to attack; return FALSE if monster evaded */
  189. /* u.dx and u.dy must be set */
  190. boolean
  191. attack(mtmp)
  192. register struct monst *mtmp;
  193. {
  194.     schar tmp;
  195.     register struct permonst *mdat = mtmp->data;
  196.  
  197.     /* This section of code provides protection against accidentally
  198.      * hitting peaceful (like '@') and tame (like 'd') monsters.
  199.      * Protection is provided as long as player is not: blind, confused,
  200.      * hallucinating or stunned.
  201.      * changes by wwp 5/16/85
  202.      * More changes 12/90, -dkh-. if its tame and safepet, (and protected
  203.      * 07/92) then we assume that you're not trying to attack. Instead,
  204.      * you'll usually just swap places if this is a movement command
  205.      */
  206.     /* Intelligent chaotic weapons (Stormbringer) want blood */
  207.     if (is_safepet(mtmp) &&
  208.         (!uwep || uwep->oartifact != ART_STORMBRINGER)) {
  209.         /* there are some additional considerations: this won't work
  210.          * if in a shop or Punished or you miss a random roll or
  211.          * if you can walk thru walls and your pet cannot (KAA) or
  212.          * if your pet is a long worm (unless someone does better).
  213.          * there's also a chance of displacing a "frozen" monster.
  214.          * sleeping monsters might magically walk in their sleep.
  215.          */
  216.         unsigned int foo = (Punished ||
  217.                     !rn2(7) || is_longworm(mtmp->data));
  218.  
  219.         if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || foo
  220. #ifdef POLYSELF
  221.             || (IS_ROCK(levl[u.ux][u.uy].typ) &&
  222.                     !passes_walls(mtmp->data))
  223. #endif
  224.             ) {
  225.             mtmp->mflee = 1;
  226.             mtmp->mfleetim = rnd(6);
  227.             You("stop.  %s is in your way!",
  228.             (mtmp->mnamelth ? NAME(mtmp) : Monnam(mtmp)));
  229.             return(TRUE);
  230.         } else if ((mtmp->mfrozen || (! mtmp->mcanmove)
  231.                 || (mtmp->data->mmove == 0)) && rn2(6)) {
  232.             pline("%s doesn't seem to move!", Monnam(mtmp));
  233.             return(TRUE);
  234.         } else return(FALSE);
  235.     }
  236.  
  237.     /* moved code to a separate function to share with dokick */
  238.     if(special_case(mtmp)) return(TRUE);
  239.  
  240. #ifdef POLYSELF
  241.     if(u.umonnum >= 0) {    /* certain "pacifist" monsters don't attack */
  242.         set_uasmon();
  243.         if(noattacks(uasmon)) {
  244.             You("have no way to attack monsters physically.");
  245.             mtmp->data->mflags3 &= ~M3_WAITMASK;
  246.             return(TRUE);
  247.         }
  248.     }
  249. #endif
  250.  
  251.     if(check_capacity("You cannot fight while so heavily loaded."))
  252.         return (TRUE);
  253.  
  254.     if(unweapon) {
  255.         unweapon=FALSE;
  256.         if(flags.verbose)
  257.         if(uwep)
  258.             You("begin bashing monsters with your %s.",
  259.             aobjnam(uwep, NULL));
  260.         else
  261. #ifdef POLYSELF
  262.             if (!cantwield(uasmon))
  263. #endif
  264.             You("begin bashing monsters with your %s hands.",
  265.             uarmg ? "gloved" : "bare");        /* Del Lamb */
  266.     }
  267.     exercise(A_STR, TRUE);        /* you're exercising muscles */
  268.     /* andrew@orca: prevent unlimited pick-axe attacks */
  269.     u_wipe_engr(3);
  270.  
  271.     if(mdat->mlet == S_LEPRECHAUN && mtmp->mfrozen && !mtmp->msleep &&
  272.        !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
  273.        (m_move(mtmp, 0) == 2 ||                /* it died */
  274.        mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* it moved */
  275.         return(FALSE);
  276.  
  277.     tmp = find_roll_to_hit(mtmp);
  278. #ifdef POLYSELF
  279.     if (u.umonnum >= 0) (void) hmonas(mtmp, tmp);
  280.     else
  281. #endif
  282.         (void) hitum(mtmp, tmp);
  283.  
  284.     mtmp->data->mflags3 &= ~M3_WAITMASK;
  285.     return(TRUE);
  286. }
  287.  
  288. static boolean
  289. known_hitum(mon, mhit)    /* returns TRUE if monster still lives */
  290. /* Made into a separate function because in some cases we want to know
  291.  * in the calling function whether we hit.
  292.  */
  293. register struct monst *mon;
  294. register int mhit;
  295. {
  296.     register boolean malive = TRUE, special;
  297.  
  298.     /* we need to know whether the special monster was peaceful */
  299.     /* before the attack, to save idle calls to angry_guards()  */
  300.     special = (mon->mpeaceful && (mon->data == &mons[PM_WATCHMAN] ||
  301.                 mon->data == &mons[PM_WATCH_CAPTAIN] ||
  302.                       mon->ispriest || mon->isshk));
  303.  
  304.     if(!mhit) {
  305.         if(flags.verbose) You("miss %s.", mon_nam(mon));
  306.         else            You("miss it.");
  307.         if(!mon->msleep && mon->mcanmove)
  308.         wakeup(mon);
  309. #ifdef MUSE
  310.         else if (uwep && uwep->otyp == TSURUGI &&
  311.              MON_WEP(mon) && !rn2(20)) {
  312.         /* 1/20 chance of shattering defender's weapon */
  313.         struct obj *obj = MON_WEP(mon);
  314.  
  315.         MON_NOWEP(mon);
  316.         m_useup(mon, obj);
  317.         pline("%s weapon shatters!", s_suffix(Monnam(mon)));
  318.         /* perhaps this will freak out the monster */
  319.         if (!rn2(3)) {
  320.             mon->mflee = 1;
  321.             mon->mfleetim += rnd(20);
  322.         }
  323.         }
  324. #endif
  325.     } else {
  326.         /* we hit the monster; be careful: it might die! */
  327.         notonhead = (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy);
  328.         if((malive = hmon(mon, uwep, 0)) == TRUE) {
  329.         /* monster still alive */
  330.         if(!rn2(25) && mon->mhp < mon->mhpmax/2) {
  331.             mon->mflee = 1;
  332.             if(!rn2(3)) mon->mfleetim = rnd(100);
  333.             if(u.ustuck == mon && !u.uswallow
  334. #ifdef POLYSELF
  335.                         && !sticks(uasmon)
  336. #endif
  337.                                 )
  338.                 u.ustuck = 0;
  339.         }
  340.         if (mon->wormno) cutworm(mon, u.ux+u.dx, u.uy+u.dy, uwep);
  341.         }
  342.         if(mon->ispriest && !rn2(2)) ghod_hitsu(mon);
  343.         if(special) (void) angry_guards(!flags.soundok);
  344.     }
  345.     return(malive);
  346. }
  347.  
  348. static boolean
  349. hitum(mon, tmp)        /* returns TRUE if monster still lives */
  350. struct monst *mon;
  351. int tmp;
  352. {
  353.     static int NEARDATA malive;
  354.     boolean mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
  355.  
  356.     if(tmp > dieroll) exercise(A_DEX, TRUE);
  357.     malive = known_hitum(mon, mhit);
  358.     (void) passive(mon, mhit, malive, FALSE);
  359.     return(malive);
  360. }
  361.  
  362. boolean            /* general "damage monster" routine */
  363. hmon(mon, obj, thrown)        /* return TRUE if mon still alive */
  364. register struct monst *mon;
  365. register struct obj *obj;
  366. register int thrown;
  367. {
  368.     int tmp;
  369.     struct permonst *mdat = mon->data;
  370.     /* Why all these booleans?  This stuff has to be done in the
  371.      *      following order:
  372.      * 1) Know what we're attacking with, and print special hittxt for
  373.      *    unusual cases.
  374.      * 2a) Know whether we did damage (depends on 1)
  375.      * 2b) Know if it's poisoned (depends on 1)
  376.      * 2c) Know whether we get a normal damage bonus or not (depends on 1)
  377.      * 3a) Know what the value of the damage bonus is (depends on 2c)
  378.      * 3b) Know how much poison damage was taken (depends on 2b) and if the
  379.      *    poison instant-killed it
  380.      * 4) Know if it was killed (requires knowing 3a, 3b) except by instant-
  381.      *    kill poison
  382.      * 5) Print hit message (depends on 1 and 4)
  383.      * 6a) Print poison message (must be done after 5)
  384. #if 0
  385.      * 6b) Rust weapon (must be done after 5)
  386. #endif
  387.      * 7) Possibly kill monster (must be done after 6a, 6b)
  388.      * 8) Instant-kill from poison (can happen anywhere between 5 and 9)
  389.      * 9) Hands not glowing (must be done after 7 and 8)
  390.      * The major problem is that since we don't want a "hit" message
  391.      * when the monster dies, we have to know how much damage it did
  392.      * _before_ outputting a hit message, but any messages associated with
  393.      * the damage don't come out until _after_ outputting a hit message.
  394.      */
  395.     boolean hittxt = FALSE, destroyed = FALSE;
  396.     boolean get_dmg_bonus = TRUE;
  397.     boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
  398.     boolean silvermsg = FALSE;
  399.  
  400.     wakeup(mon);
  401.     if(!obj) {    /* attack with bare hands */
  402.         if (mdat == &mons[PM_SHADE])
  403.         tmp = 0;
  404.         else
  405.         tmp = rnd(2);
  406. #if 0
  407.         if(mdat == &mons[PM_COCKATRICE] && !uarmg
  408. #ifdef POLYSELF
  409.         && !resists_ston(uasmon)
  410. #endif
  411.         ) {
  412.  
  413.         You("hit %s with your bare %s.",
  414.             mon_nam(mon), makeplural(body_part(HAND)));
  415. # ifdef POLYSELF
  416.         if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  417.             return TRUE;
  418. # endif
  419.         You("turn to stone...");
  420.         done_in_by(mon);
  421.         hittxt = TRUE; /* maybe lifesaved */
  422.         }
  423. #endif
  424.     } else {
  425.         if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
  426.            obj->otyp == UNICORN_HORN || obj->oclass == ROCK_CLASS) {
  427.  
  428.         /* If not a melee weapon, and either not thrown, or thrown */
  429.         /* and a bow (bows are >BOOMERANG), or thrown and a missile */
  430.         /* without a propellor (missiles are <DART), do 1-2 points */
  431.         if((obj->otyp >= BOW || obj->otyp < DART)
  432.             && obj->otyp != PICK_AXE && obj->otyp != UNICORN_HORN
  433.             && (!thrown ||
  434.                 (obj->oclass != ROCK_CLASS &&
  435.                 (obj->otyp > BOOMERANG ||
  436.                 (obj->otyp < DART &&
  437.                     (!uwep ||
  438.                     objects[obj->otyp].w_propellor !=
  439.                     -objects[uwep->otyp].w_propellor)
  440.                 ))))) {
  441.             if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
  442.             tmp = 0;
  443.             else
  444.             tmp = rnd(2);
  445.         } else {
  446.             tmp = dmgval(obj, mdat);
  447.             if (obj->oartifact &&
  448.             artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
  449.             if(mon->mhp <= 0) /* artifact killed monster */
  450.                 return FALSE;
  451.             hittxt = TRUE;
  452.             }
  453.             if (objects[obj->otyp].oc_material == SILVER
  454.                 && hates_silver(mdat))
  455.             silvermsg = TRUE;
  456.             if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
  457.                !rnl(3)) {
  458.             pline("As you hit %s, %s breaks into splinters.",
  459.                   mon_nam(mon), the(xname(obj)));
  460.             useup(obj);
  461.             obj = (struct obj *) 0;
  462.             hittxt = TRUE;
  463.             if (mdat != &mons[PM_SHADE])
  464.                 tmp++;
  465.             } else if(thrown &&
  466.                   (obj->otyp >= ARROW && obj->otyp <= SHURIKEN)) {
  467.             if(uwep && obj->otyp < DART &&
  468.                objects[obj->otyp].w_propellor ==
  469.                -objects[uwep->otyp].w_propellor) {
  470.                 /* Elves and Samurai do extra damage using
  471.                  * their bows&arrows; they're highly trained.
  472.                  */
  473.                 if (pl_character[0] == 'S' &&
  474.                 obj->otyp == YA && uwep->otyp == YUMI)
  475.                 tmp++;
  476.                 else if (pl_character[0] == 'E' &&
  477.                      obj->otyp == ELVEN_ARROW &&
  478.                      uwep->otyp == ELVEN_BOW)
  479.                 tmp++;
  480.             }
  481.             if(((uwep && objects[obj->otyp].w_propellor ==
  482.                 -objects[uwep->otyp].w_propellor)
  483.                 || obj->otyp==DART || obj->otyp==SHURIKEN) &&
  484.                 obj->opoisoned)
  485.                 ispoisoned = TRUE;
  486.             }
  487.         }
  488.         } else if(obj->oclass == POTION_CLASS) {
  489.             if (obj->quan > 1L) setuwep(splitobj(obj, 1L));
  490.             else setuwep((struct obj *)0);
  491.             freeinv(obj);
  492.             potionhit(mon,obj);
  493.             hittxt = TRUE;
  494.             if (mdat == &mons[PM_SHADE])
  495.                 tmp = 0;
  496.             else
  497.                 tmp = 1;
  498.         } else {
  499.         switch(obj->otyp) {
  500.             case HEAVY_IRON_BALL:
  501.             tmp = rnd(25); break;
  502.             case BOULDER:
  503.             tmp = rnd(20); break;
  504.             case MIRROR:
  505.             You("break your mirror.  That's bad luck!");
  506.             change_luck(-2);
  507.             useup(obj);
  508.             obj = (struct obj *) 0;
  509.             hittxt = TRUE;
  510.             tmp = 1;
  511.             break;
  512. #ifdef TOURIST
  513.             case EXPENSIVE_CAMERA:
  514.     You("succeed in destroying your camera.  Congratulations!");
  515.             useup(obj);
  516.             return(TRUE);
  517. #endif
  518.             case CORPSE:        /* fixed by polder@cs.vu.nl */
  519.             if(obj->corpsenm == PM_COCKATRICE) {
  520.                 You("hit %s with the cockatrice corpse.",
  521.                   mon_nam(mon));
  522.                 if(resists_ston(mdat)) {
  523.                 tmp = 1;
  524.                 hittxt = TRUE;
  525.                 break;
  526.                 }
  527.                 if(poly_when_stoned(mdat)) {
  528.                 mon_to_stone(mon);
  529.                 tmp = 1;
  530.                 hittxt = TRUE;
  531.                 break;
  532.                 }
  533.                 pline("%s turns to stone.", Monnam(mon));
  534.                 stoned = TRUE;
  535.                 xkilled(mon,0);
  536.                 return(FALSE);
  537.             }
  538.             tmp = mons[obj->corpsenm].msize + 1;
  539.             break;
  540.             case EGG: /* only possible if hand-to-hand */
  541.             if(obj->corpsenm > -1
  542.                     && obj->corpsenm != PM_COCKATRICE
  543.                     && mdat == &mons[PM_COCKATRICE]) {
  544.                 You("hit %s with the %s egg%s.",
  545.                     mon_nam(mon),
  546.                     mons[obj->corpsenm].mname,
  547.                     plur(obj->quan));
  548.                 hittxt = TRUE;
  549.                 pline("The egg%sn't live any more...",
  550.                     (obj->quan == 1L) ? " is" : "s are");
  551.                 obj->otyp = ROCK;
  552.                 obj->oclass = GEM_CLASS;
  553.                 obj->known = obj->dknown = 0;
  554.                 obj->owt = weight(obj);
  555.             }
  556.             tmp = 1;
  557.             break;
  558.             case CLOVE_OF_GARLIC:    /* no effect against demons */
  559.             if(is_undead(mdat)) mon->mflee = 1;
  560.             tmp = 1;
  561.             break;
  562.             case CREAM_PIE:
  563. #ifdef POLYSELF
  564.             case BLINDING_VENOM:
  565.             if(Blind || !haseyes(mon->data))
  566.                 pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
  567.             else if (obj->otyp == BLINDING_VENOM)
  568.                 pline("The venom blinds %s%s!", mon_nam(mon),
  569.                     mon->mcansee ? "" : " further");
  570. #else
  571.             if(Blind) pline("Splat!");
  572. #endif
  573.             else
  574.                 pline("The cream pie splashes over %s%s!",
  575.                 mon_nam(mon),
  576.                 (haseyes(mdat) &&
  577.                     mdat != &mons[PM_FLOATING_EYE])
  578.                 ? (*(eos(mon_nam(mon))-1) == 's' ? "' face" :
  579.                      "'s face") : "");
  580.             if(mon->msleep) mon->msleep = 0;
  581.             setmangry(mon);
  582.             if(haseyes(mon->data)) {
  583.                 mon->mcansee = 0;
  584.                 tmp = rn1(25, 21);
  585.                 if(((int) mon->mblinded + tmp) > 127)
  586.                 mon->mblinded = 127;
  587.                 else mon->mblinded += tmp;
  588.             }
  589.             hittxt = TRUE;
  590.             get_dmg_bonus = FALSE;
  591.             tmp = 0;
  592.             break;
  593. #ifdef POLYSELF
  594.             case ACID_VENOM: /* only possible if thrown */
  595.             if(resists_acid(mdat)) {
  596.                 Your("venom hits %s harmlessly.",
  597.                     mon_nam(mon));
  598.                 tmp = 0;
  599.             } else {
  600.                 Your("venom burns %s!", mon_nam(mon));
  601.                 tmp = dmgval(obj, mdat);
  602.             }
  603.             hittxt = TRUE;
  604.             get_dmg_bonus = FALSE;
  605.             break;
  606. #endif
  607.             default:
  608.             /* non-weapons can damage because of their weight */
  609.             /* (but not too much) */
  610.             tmp = obj->owt/100;
  611.             if(tmp < 1) tmp = 1;
  612.             else tmp = rnd(tmp);
  613.             if(tmp > 6) tmp = 6;
  614.         }
  615.         if (mdat == &mons[PM_SHADE] && obj &&
  616.                 objects[obj->otyp].oc_material != SILVER)
  617.             tmp = 0;
  618.         }
  619.     }
  620.  
  621.     /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
  622.      *      *OR* if attacking bare-handed!! */
  623.  
  624.     if (get_dmg_bonus && tmp) {
  625.         tmp += u.udaminc;
  626.         /* If you throw using a propellor, you don't get a strength
  627.          * bonus but you do get an increase-damage bonus.
  628.          */
  629.         if(!thrown || !obj || !uwep ||
  630.            (obj->oclass != GEM_CLASS && obj->oclass != WEAPON_CLASS) ||
  631.            !objects[obj->otyp].w_propellor ||
  632.            (objects[obj->otyp].w_propellor !=
  633.                 -objects[uwep->otyp].w_propellor))
  634.             tmp += dbon();
  635.     }
  636.  
  637. /* TODO:    Fix this up.  multiple engulf attacks now exist.
  638.     if(u.uswallow) {
  639.         if((tmp -= u.uswldtim) <= 0) {
  640.         Your("%s are no longer able to hit.",
  641.             makeplural(body_part(ARM)));
  642.         return(TRUE);
  643.         }
  644.     }
  645.  */
  646.     if (ispoisoned) {
  647.         if(resists_poison(mdat))
  648.         needpoismsg = TRUE;
  649.         else if (rn2(10))
  650.         tmp += rnd(6);
  651.         else poiskilled = TRUE;
  652.     }
  653.     if(tmp < 1)
  654.         if (mdat == &mons[PM_SHADE]) {
  655.         Your("attack passes harmlessly through %s.",
  656.             mon_nam(mon));
  657.         hittxt = TRUE;
  658.         } else
  659.         tmp = 1;
  660.  
  661.     mon->mhp -= tmp;
  662.     if(mon->mhp < 1)
  663.         destroyed = TRUE;
  664.     if(mon->mtame && (!mon->mflee || mon->mfleetim)) {
  665. #ifdef SOUNDS
  666.         if (rn2(8)) yelp(mon);
  667.         else growl(mon); /* give them a moment's worry */
  668. #endif
  669.         mon->mtame--;
  670.         if(!mon->mtame) newsym(mon->mx, mon->my);
  671.         mon->mflee = TRUE;        /* Rick Richardson */
  672.         mon->mfleetim += 10*rnd(tmp);
  673.     }
  674.     if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
  675.            && obj && obj == uwep
  676.            && objects[obj->otyp].oc_material == IRON
  677.            && mon->mhp > 1 && !thrown && !mon->mcan
  678.            /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
  679.  
  680.         if (clone_mon(mon)) {
  681.             pline("%s divides as you hit it!", Monnam(mon));
  682.             hittxt = TRUE;
  683.         }
  684.     }
  685.  
  686.     if(!hittxt && !destroyed) {
  687.         if(thrown)
  688.             /* thrown => obj exists */
  689.             hit(xname(obj), mon, exclam(tmp) );
  690.         else if(!flags.verbose) You("hit it.");
  691.         else    You("hit %s%s", mon_nam(mon), canseemon(mon)
  692.             ? exclam(tmp) : ".");
  693.     }
  694.  
  695.     if (silvermsg) {
  696.         if (canseemon(mon) || sensemon(mon))
  697.             pline("The silver sears %s%s!",
  698.                 mon_nam(mon),
  699.                 noncorporeal(mdat) ? "" : 
  700.                       (*(eos(mon_nam(mon))-1) == 's' ?
  701.                        "' flesh" : "'s flesh"));
  702.         else
  703.             pline("It%s is seared!",
  704.                 noncorporeal(mdat) ? "" : "s flesh");
  705.     }
  706.  
  707.     if (needpoismsg)
  708.         pline("The poison doesn't seem to affect %s.", mon_nam(mon));
  709.     if (poiskilled) {
  710.         pline("The poison was deadly...");
  711.         xkilled(mon, 0);
  712.         return FALSE;
  713.     } else if (destroyed) {
  714.         killed(mon);    /* takes care of most messages */
  715.     } else if(u.umconf && !thrown) {
  716.         nohandglow(mon);
  717.         if(!mon->mconf && !resist(mon, '+', 0, NOTELL)) {
  718.             mon->mconf = 1;
  719.             if(!mon->mstun && mon->mcanmove && !mon->msleep &&
  720.                !Blind)
  721.                 pline("%s appears confused.", Monnam(mon));
  722.         }
  723.     }
  724.  
  725. #if 0
  726.     if(mdat == &mons[PM_RUST_MONSTER] && obj && obj == uwep &&
  727.         is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
  728.         if (obj->greased)
  729.         grease_protect(obj,NULL,FALSE);
  730.         else if (obj->oerodeproof || (obj->blessed && !rnl(4))) {
  731.             if (flags.verbose)
  732.             pline("Somehow, your %s is not affected.",
  733.                   is_sword(obj) ? "sword" : "weapon");
  734.         } else {
  735.         Your("%s%s!", aobjnam(obj, "rust"),
  736.              obj->oeroded+1 == MAX_ERODE ? " completely" :
  737.              obj->oeroded ? " further" : "");
  738.         obj->oeroded++;
  739.         }
  740.     }
  741. #endif
  742.  
  743.     return(destroyed ? FALSE : TRUE);
  744. }
  745.  
  746. #ifdef POLYSELF
  747.  
  748. int
  749. damageum(mdef, mattk)
  750. register struct monst *mdef;
  751. register struct attack *mattk;
  752. {
  753.     register struct permonst *pd = mdef->data;
  754.     register int    tmp = d((int)mattk->damn, (int)mattk->damd);
  755.  
  756.     if (is_demon(uasmon) && !rn2(13) && !uwep
  757.         && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
  758.         && u.umonnum != PM_BALROG) {
  759.         struct monst *dtmp;
  760.         pline("Some hell-p has arrived!");
  761.         if((dtmp = makemon(!rn2(6) ? &mons[ndemon()] : uasmon, u.ux, u.uy)))
  762.         (void)tamedog(dtmp, (struct obj *)0);
  763.         exercise(A_WIS, TRUE);
  764.         return(0);
  765.     }
  766.  
  767.     switch(mattk->adtyp) {
  768.         case AD_STUN:
  769.         if(!Blind)
  770.             pline("%s staggers for a moment.", Monnam(mdef));
  771.         mdef->mstun = 1;
  772.         /* fall through to next case */
  773.         case AD_WERE:        /* no effect on monsters */
  774.         case AD_HEAL:
  775.         case AD_LEGS:
  776.         case AD_PHYS:
  777.         if(mattk->aatyp == AT_WEAP) {
  778.             if(uwep) tmp = 0;
  779.         } else if(mattk->aatyp == AT_KICK)
  780.             if(thick_skinned(mdef->data)) tmp = 0;
  781.         break;
  782.         case AD_FIRE:
  783.         if(!Blind) pline("%s is on fire!", Monnam(mdef));
  784.         tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
  785.         tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
  786.         if(resists_fire(pd)) {
  787.             if (!Blind)
  788.             pline("The fire doesn't heat %s!", mon_nam(mdef));
  789.             golemeffects(mdef, AD_FIRE, tmp);
  790.             shieldeff(mdef->mx, mdef->my);
  791.             tmp = 0;
  792.         }
  793.         /* only potions damage resistant players in destroy_item */
  794.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
  795.         break;
  796.         case AD_COLD:
  797.         if(!Blind) pline("%s is covered in frost!", Monnam(mdef));
  798.         if(resists_cold(pd)) {
  799.             shieldeff(mdef->mx, mdef->my);
  800.             if (!Blind)
  801.             pline("The frost doesn't chill %s!", mon_nam(mdef));
  802.             golemeffects(mdef, AD_COLD, tmp);
  803.             tmp = 0;
  804.         }
  805.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
  806.         break;
  807.         case AD_ELEC:
  808.         if (!Blind) pline("%s is zapped!", Monnam(mdef));
  809.         tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
  810.         if(resists_elec(pd)) {
  811.             if (!Blind)
  812.             pline("The zap doesn't shock %s!", mon_nam(mdef));
  813.             golemeffects(mdef, AD_ELEC, tmp);
  814.             shieldeff(mdef->mx, mdef->my);
  815.             tmp = 0;
  816.         }
  817.         /* only rings damage resistant players in destroy_item */
  818.         tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
  819.         break;
  820.         case AD_ACID:
  821.         if(resists_acid(pd)) tmp = 0;
  822.         break;
  823.         case AD_STON:
  824.         if(poly_when_stoned(pd))
  825.            mon_to_stone(mdef);
  826.         else if(!resists_ston(pd)) {
  827.             stoned = TRUE;
  828.             if(!Blind) pline("%s turns to stone.", Monnam(mdef));
  829.             xkilled(mdef, 0);
  830.             return(2);
  831.         }
  832.         tmp = 0;    /* no damage if this fails */
  833.         break;
  834. # ifdef SEDUCE
  835.         case AD_SSEX:
  836. # endif
  837.         case AD_SEDU:
  838.         case AD_SITM:
  839.         if(mdef->minvent) {
  840.             struct obj *otmp, *stealoid;
  841.  
  842.             stealoid = (struct obj *)0;
  843.         /* Without MUSE we can only change a monster's AC by stealing
  844.          * armor with the "unarmored soldier" kludge.  With it there
  845.          * are many monsters which wear armor, and all can be stripped.
  846.          */
  847.             if(
  848. #ifndef MUSE
  849.             is_mercenary(pd) &&
  850. #endif
  851.                     could_seduce(&youmonst,mdef,mattk)){
  852.             for(otmp = mdef->minvent; otmp; otmp=otmp->nobj)
  853. #ifdef MUSE
  854.                 if (otmp->owornmask & W_ARM) stealoid = otmp;
  855. #else
  856.                 if (otmp->otyp >= PLATE_MAIL && otmp->otyp
  857.                 <= ELVEN_CLOAK) stealoid = otmp;
  858. #endif
  859.             }
  860.             if (stealoid) {
  861.             boolean stolen = FALSE;
  862.             /* Is "he"/"his" always correct? */
  863.             if (gender(mdef) == u.mfemale &&
  864.                         uasmon->mlet == S_NYMPH)
  865.     You("charm %s.  She gladly hands over her possessions.", mon_nam(mdef));
  866.             else
  867.         You("seduce %s and %s starts to take off %s clothes.",
  868.                 mon_nam(mdef),
  869.                 gender(mdef) ? "she" : "he",
  870.                 gender(mdef) ? "her" : "his");
  871.             while(mdef->minvent) {
  872.                 otmp = mdef->minvent;
  873.                 mdef->minvent = otmp->nobj;
  874.                 /* set dknown to insure proper merge */
  875.                 if (!Blind) otmp->dknown = 1;
  876. #ifdef MUSE
  877.                 otmp->owornmask = 0L;
  878. #endif
  879.                 if (!stolen && otmp==stealoid) {
  880.                     otmp = hold_another_object(otmp,
  881.                           (const char *)0, (const char *)0,
  882.                                   (const char *)0);
  883.                     stealoid = otmp;
  884.                     stolen = TRUE;
  885.                 } else {
  886.                     otmp = hold_another_object(otmp,
  887.                          "You steal %s.", doname(otmp),
  888.                                 "You steal: ");
  889.                 }
  890.             }
  891.             if (!stolen)
  892.                 impossible("Player steal fails!");
  893.             else {
  894.                 pline("%s finishes taking off %s suit.",
  895.                    Monnam(mdef), gender(mdef) ? "her" : "his");
  896.                 You("steal %s!", doname(stealoid));
  897. # if defined(ARMY) && !defined(MUSE)
  898.                 mdef->data = &mons[PM_UNARMORED_SOLDIER];
  899. # endif
  900.             }
  901. #ifdef MUSE
  902.             possibly_unwield(mdef);
  903.             mdef->misc_worn_check = 0L;
  904. #endif
  905.            } else {
  906.             otmp = mdef->minvent;
  907.             mdef->minvent = otmp->nobj;
  908.             otmp = hold_another_object(otmp, "You steal %s.",
  909.                           doname(otmp), "You steal: ");
  910. #ifdef MUSE
  911.             possibly_unwield(mdef);
  912.             otmp->owornmask = 0L;
  913. #endif
  914.            }
  915.         }
  916.         tmp = 0;
  917.         break;
  918.         case AD_SGLD:
  919.         if (mdef->mgold) {
  920.             u.ugold += mdef->mgold;
  921.             mdef->mgold = 0;
  922.             Your("purse feels heavier.");
  923.         }
  924.         exercise(A_DEX, TRUE);
  925.         tmp = 0;
  926.         break;
  927.         case AD_TLPT:
  928.         if(tmp <= 0) tmp = 1;
  929.         if(tmp < mdef->mhp) {
  930.             rloc(mdef);
  931.             if(!Blind) pline("%s suddenly disappears!", Monnam(mdef));
  932.         }
  933.         break;
  934.         case AD_BLND:
  935.         if(haseyes(pd)) {
  936.  
  937.             if(!Blind) pline("%s is blinded.", Monnam(mdef));
  938.             mdef->mcansee = 0;
  939.             mdef->mblinded += tmp;
  940.         }
  941.         tmp = 0;
  942.         break;
  943.         case AD_CURS:
  944.         if (night() && !rn2(10) && !mdef->mcan) {
  945.             if (mdef->data == &mons[PM_CLAY_GOLEM]) {
  946.             if (!Blind)
  947.                 pline("Some writing vanishes from %s head!",
  948.                 s_suffix(mon_nam(mdef)));
  949.             xkilled(mdef, 0);
  950.             return 2;
  951.             }
  952.             mdef->mcan = 1;
  953.             You("chuckle.");
  954.         }
  955.         tmp = 0;
  956.         break;
  957.         case AD_DRLI:
  958.         if(rn2(2) && !resists_drli(pd)) {
  959.             int xtmp = d(2,6);
  960.             pline("%s suddenly seems weaker!", Monnam(mdef));
  961.             mdef->mhpmax -= xtmp;
  962.             if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev--) {
  963.                 pline("%s dies!", Monnam(mdef));
  964.                 xkilled(mdef,0);
  965.                 return(2);
  966.             }
  967.         }
  968.         tmp = 0;
  969.         break;
  970.         case AD_RUST:
  971.         if (pd == &mons[PM_IRON_GOLEM]) {
  972.             pline("%s falls to pieces!", Monnam(mdef));
  973.             xkilled(mdef,0);
  974.             return(2);
  975.         }
  976.         tmp = 0;
  977.         break;
  978.         case AD_DCAY:
  979.         if (pd == &mons[PM_WOOD_GOLEM] ||
  980.             pd == &mons[PM_LEATHER_GOLEM]) {
  981.             pline("%s falls to pieces!", Monnam(mdef));
  982.             xkilled(mdef,0);
  983.             return(2);
  984.         }
  985.         case AD_DRST:
  986.         case AD_DRDX:
  987.         case AD_DRCO:
  988.         if (!rn2(8)) {
  989.             Your("%s was poisoned!", mattk->aatyp==AT_BITE ?
  990.             "bite" : "sting");
  991.             if (resists_poison(mdef->data))
  992.             pline("The poison doesn't seem to affect %s.",
  993.                 mon_nam(mdef));
  994.             else {
  995.             if (!rn2(10)) {
  996.                 Your("poison was deadly...");
  997.                 tmp = mdef->mhp;
  998.             } else tmp += rn1(10,6);
  999.             }
  1000.         }
  1001.         break;
  1002.         case AD_DRIN:
  1003.         if (!has_head(mdef->data)) {
  1004.             pline("%s doesn't seem harmed.", Monnam(mdef));
  1005.             tmp = 0;
  1006.             break;
  1007.         }
  1008. #ifdef MUSE
  1009.         if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
  1010.             pline("%s helmet blocks your attack to %s head.",
  1011.               s_suffix(Monnam(mdef)),
  1012.               (Blind || !humanoid(mdef->data)) ? "its" :
  1013.                 (mdef->female ? "her" : "his"));
  1014.             break;
  1015.         }
  1016. #endif
  1017.         You("eat %s brain!", s_suffix(mon_nam(mdef)));
  1018.         if (mindless(mdef->data)) {
  1019.             pline("%s doesn't notice.", Monnam(mdef));
  1020.             break;
  1021.         }
  1022.         tmp += rnd(10);
  1023.         morehungry(-rnd(30)); /* cannot choke */
  1024.         if (ABASE(A_INT) < AMAX(A_INT)) {
  1025.             ABASE(A_INT) += rnd(4);
  1026.             if (ABASE(A_INT) > AMAX(A_INT))
  1027.                 ABASE(A_INT) = AMAX(A_INT);
  1028.             flags.botl = 1;
  1029.         }
  1030.         exercise(A_WIS, TRUE);
  1031.         break;
  1032.         case AD_WRAP:
  1033.         case AD_STCK:
  1034.         if (!sticks(mdef->data))
  1035.             u.ustuck = mdef; /* it's now stuck to you */
  1036.         break;
  1037.         case AD_PLYS:
  1038.         if (mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
  1039.             if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
  1040.             mdef->mcanmove = 0;
  1041.             mdef->mfrozen = rnd(10);
  1042.         }
  1043.         break;
  1044.         case AD_SLEE:
  1045.         if (!resists_sleep(mdef->data) && !mdef->msleep &&
  1046.                             mdef->mcanmove) {
  1047.             if (!Blind)
  1048.             pline("%s suddenly falls asleep!", Monnam(mdef));
  1049.             mdef->mcanmove = 0;
  1050.             mdef->mfrozen = rnd(10);
  1051.         }
  1052.         break;
  1053.         default:    tmp = 0;
  1054.             break;
  1055.     }
  1056.     if(!tmp) return(1);
  1057.  
  1058.     if((mdef->mhp -= tmp) < 1) {
  1059.  
  1060.         if (mdef->mtame && !cansee(mdef->mx,mdef->my)) {
  1061.         You("feel embarrassed for a moment.");
  1062.         xkilled(mdef, 0);
  1063.         } else if (!flags.verbose) {
  1064.         You("destroy it!");
  1065.         xkilled(mdef, 0);
  1066.         } else
  1067.         killed(mdef);
  1068.         return(2);
  1069.     }
  1070.     return(1);
  1071. }
  1072.  
  1073. static int
  1074. explum(mdef, mattk)
  1075. register struct monst *mdef;
  1076. register struct attack *mattk;
  1077. {
  1078.     register int tmp = d((int)mattk->damn, (int)mattk->damd);
  1079.  
  1080.     You("explode!");
  1081.     switch(mattk->adtyp) {
  1082.         case AD_BLND:
  1083.         if (haseyes(mdef->data)) {
  1084.             pline("%s is blinded by your flash of light!", Monnam(mdef));
  1085.             if (mdef->mcansee) {
  1086.             mdef->mblinded += tmp;
  1087.             mdef->mcansee = 0;
  1088.             }
  1089.         }
  1090.         break;
  1091.         case AD_COLD:
  1092.         if (!resists_cold(mdef->data)) {
  1093.             pline("%s gets blasted!", Monnam(mdef));
  1094.             mdef->mhp -= tmp;
  1095.             if (mdef->mhp <= 0) {
  1096.              killed(mdef);
  1097.              return(2);
  1098.             }
  1099.         } else {
  1100.             shieldeff(mdef->mx, mdef->my);
  1101.             if (is_golem(mdef->data))
  1102.             golemeffects(mdef, AD_COLD, tmp);
  1103.             else
  1104.             pline("The blast doesn't seem to affect %s.",
  1105.                 mon_nam(mdef));
  1106.         }
  1107.         break;
  1108.         default:
  1109.         break;
  1110.     }
  1111.     return(1);
  1112. }
  1113.  
  1114. static int
  1115. gulpum(mdef,mattk)
  1116. register struct monst *mdef;
  1117. register struct attack *mattk;
  1118. {
  1119.     register int tmp;
  1120.     register int dam = d((int)mattk->damn, (int)mattk->damd);
  1121.     /* Not totally the same as for real monsters.  Specifically, these
  1122.      * don't take multiple moves.  (It's just too hard, for too little
  1123.      * result, to program monsters which attack from inside you, which
  1124.      * would be necessary if done accurately.)  Instead, we arbitrarily
  1125.      * kill the monster immediately for AD_DGST and we regurgitate them
  1126.      * after exactly 1 round of attack otherwise.  -KAA
  1127.      */
  1128.  
  1129.     if(mdef->data->msize >= MZ_HUGE) return 0;
  1130.  
  1131.     if(u.uhunger < 1500 && !u.uswallow) {
  1132.  
  1133.         if(mdef->data->mlet != S_COCKATRICE) {
  1134. # ifdef LINT    /* static char msgbuf[BUFSZ]; */
  1135.         char msgbuf[BUFSZ];
  1136. # else
  1137.         static char msgbuf[BUFSZ];
  1138. # endif
  1139. /* TODO: get the symbol display also to work (monster symbol is removed from
  1140.  * the screen and you moved onto it, then you get moved back and it gets
  1141.  * moved back if the monster survives--just like when monsters swallow you.
  1142.  */
  1143.         You("engulf %s!", mon_nam(mdef));
  1144.         switch(mattk->adtyp) {
  1145.             case AD_DGST:
  1146.             u.uhunger += mdef->data->cnutrit;
  1147.             newuhs(FALSE);
  1148.             xkilled(mdef,2);
  1149.             Sprintf(msgbuf, "You totally digest %s.",
  1150.                     mon_nam(mdef));
  1151.             if ((tmp = 3 + (mdef->data->cwt >> 6)) != 0) {
  1152.                 You("digest %s.", mon_nam(mdef));
  1153.                 nomul(-tmp);
  1154.                 nomovemsg = msgbuf;
  1155.             } else pline(msgbuf);
  1156.             exercise(A_CON, TRUE);
  1157.             return(2);
  1158.             case AD_PHYS:
  1159.             pline("%s is pummeled with your debris!",Monnam(mdef));
  1160.             break;
  1161.             case AD_ACID:
  1162.             pline("%s is covered with your goo!", Monnam(mdef));
  1163.             if (resists_acid(mdef->data)) {
  1164.                 pline("It seems harmless to %s.", mon_nam(mdef));
  1165.                 dam = 0;
  1166.             }
  1167.             break;
  1168.             case AD_BLND:
  1169.             if(haseyes(mdef->data)) {
  1170.                 if (mdef->mcansee)
  1171.                 pline("%s can't see in there!", Monnam(mdef));
  1172.                 mdef->mcansee = 0;
  1173.                 dam += mdef->mblinded;
  1174.                 if (dam > 127) dam = 127;
  1175.                 mdef->mblinded = dam;
  1176.             }
  1177.             dam = 0;
  1178.             break;
  1179.             case AD_ELEC:
  1180.             if (rn2(2)) {
  1181.                 pline("The air around %s crackles with electricity.", mon_nam(mdef));
  1182.                 if (resists_elec(mdef->data)) {
  1183.                 pline("%s seems unhurt.", Monnam(mdef));
  1184.                 dam = 0;
  1185.                 }
  1186.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1187.             } else dam = 0;
  1188.             break;
  1189.             case AD_COLD:
  1190.             if (rn2(2)) {
  1191.                 if (resists_cold(mdef->data)) {
  1192.                 pline("%s seems mildly chilly.", Monnam(mdef));
  1193.                 dam = 0;
  1194.                 } else
  1195.                 pline("%s is freezing to death!",Monnam(mdef));
  1196.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1197.             } else dam = 0;
  1198.             break;
  1199.             case AD_FIRE:
  1200.             if (rn2(2)) {
  1201.                 if (resists_fire(mdef->data)) {
  1202.                 pline("%s seems mildly hot.", Monnam(mdef));
  1203.                 dam = 0;
  1204.                 } else
  1205.                 pline("%s is burning to a crisp!",Monnam(mdef));
  1206.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1207.             } else dam = 0;
  1208.             break;
  1209.         }
  1210.         if ((mdef->mhp -= dam) <= 0) {
  1211.             killed(mdef);
  1212.             return(2);
  1213.         }
  1214.         You("%s %s!", is_animal(uasmon) ? "regurgitate"
  1215.             : "expel", mon_nam(mdef));
  1216.         if (is_animal(uasmon)) {
  1217.             pline("Obviously, you didn't like %s taste.",
  1218.               s_suffix(mon_nam(mdef)));
  1219.         }
  1220.         } else {
  1221.         You("bite into %s", mon_nam(mdef));
  1222.         You("turn to stone...");
  1223.         killer_format = KILLED_BY;
  1224.         killer = "swallowing a cockatrice whole";
  1225.         done(STONING);
  1226.         }
  1227.     }
  1228.     return(0);
  1229. }
  1230.  
  1231. void
  1232. missum(mdef,mattk)
  1233. register struct monst *mdef;
  1234. register struct attack *mattk;
  1235. {
  1236.     if (could_seduce(&youmonst, mdef, mattk))
  1237.         You("pretend to be friendly to %s.", mon_nam(mdef));
  1238.     else if(!Blind && flags.verbose)
  1239.         You("miss %s.", mon_nam(mdef));
  1240.     else
  1241.         You("miss it.");
  1242.     wakeup(mdef);
  1243. }
  1244.  
  1245. static boolean
  1246. hmonas(mon, tmp)        /* attack monster as a monster. */
  1247. register struct monst *mon;
  1248. register int tmp;
  1249. {
  1250.     register struct attack *mattk;
  1251.     int    i, sum[NATTK];
  1252.     int    nsum = 0;
  1253.     schar    dhit;
  1254.  
  1255. #ifdef GCC_WARN
  1256.     dhit = 0;
  1257. #endif
  1258.  
  1259.     for(i = 0; i < NATTK; i++) {
  1260.  
  1261.         sum[i] = 0;
  1262.         mattk = &(uasmon->mattk[i]);
  1263.         switch(mattk->aatyp) {
  1264.         case AT_WEAP:
  1265. use_weapon:
  1266.     /* Certain monsters don't use weapons when encountered as enemies,
  1267.      * but players who polymorph into them have hands or claws and thus
  1268.      * should be able to use weapons.  This shouldn't prohibit the use
  1269.      * of most special abilities, either.
  1270.      */
  1271.     /* Potential problem: if the monster gets multiple weapon attacks,
  1272.      * we currently allow the player to get each of these as a weapon
  1273.      * attack.  Is this really desirable?
  1274.      */
  1275.             if(uwep) tmp += hitval(uwep, mon->data);
  1276.             dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
  1277.             /* Enemy dead, before any special abilities used */
  1278.             if (!known_hitum(mon,dhit)) return 0;
  1279.             /* might be a worm that gets cut in half */
  1280.             if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return(nsum);
  1281.             /* Do not print "You hit" message, since known_hitum
  1282.              * already did it.
  1283.              */
  1284.             if (dhit && mattk->adtyp != AD_SPEL
  1285.                 && mattk->adtyp != AD_PHYS)
  1286.                 sum[i] = damageum(mon,mattk);
  1287.             break;
  1288.         case AT_CLAW:
  1289.             if (i==0 && uwep && !cantwield(uasmon)) goto use_weapon;
  1290. # ifdef SEDUCE
  1291.             /* succubi/incubi are humanoid, but their _second_
  1292.              * attack is AT_CLAW, not their first...
  1293.              */
  1294.             if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
  1295.                 u.umonnum == PM_INCUBUS)) goto use_weapon;
  1296. # endif
  1297.         case AT_KICK:
  1298.         case AT_BITE:
  1299.         case AT_STNG:
  1300.         case AT_TUCH:
  1301.         case AT_BUTT:
  1302.         case AT_TENT:
  1303.             if (i==0 && uwep && (u.usym==S_LICH)) goto use_weapon;
  1304.             if ((dhit = (tmp > rnd(20) || u.uswallow)) != 0) {
  1305.                 int compat;
  1306.  
  1307.                 if (!u.uswallow &&
  1308.                 (compat=could_seduce(&youmonst, mon, mattk))) {
  1309.                 You("%s %s %s.",
  1310.                     mon->mcansee && haseyes(mon->data)
  1311.                     ? "smile at" : "talk to",
  1312.                     mon_nam(mon),
  1313.                     compat == 2 ? "engagingly":"seductively");
  1314.                 /* doesn't anger it; no wakeup() */
  1315.                 sum[i] = damageum(mon, mattk);
  1316.                 break;
  1317.                 }
  1318.                 wakeup(mon);
  1319.                 if (mon->data == &mons[PM_SHADE]) {
  1320.                 Your("attack passes harmlessly through %s.",
  1321.                     mon_nam(mon));
  1322.                 break;
  1323.                 }
  1324.                 if (mattk->aatyp == AT_KICK)
  1325.                     You("kick %s.", mon_nam(mon));
  1326.                 else if (mattk->aatyp == AT_BITE)
  1327.                     You("bite %s.", mon_nam(mon));
  1328.                 else if (mattk->aatyp == AT_STNG)
  1329.                     You("sting %s.", mon_nam(mon));
  1330.                 else if (mattk->aatyp == AT_BUTT)
  1331.                     You("butt %s.", mon_nam(mon));
  1332.                 else if (mattk->aatyp == AT_TUCH)
  1333.                     You("touch %s.", mon_nam(mon));
  1334.                 else if (mattk->aatyp == AT_TENT)
  1335.                     Your("tentacles suck %s.", mon_nam(mon));
  1336.                 else You("hit %s.", mon_nam(mon));
  1337.                 sum[i] = damageum(mon, mattk);
  1338.             } else
  1339.                 missum(mon, mattk);
  1340.             break;
  1341.  
  1342.         case AT_HUGS:
  1343.             /* automatic if prev two attacks succeed, or if
  1344.              * already grabbed in a previous attack
  1345.              */
  1346.             dhit = 1;
  1347.             wakeup(mon);
  1348.             if (mon->data == &mons[PM_SHADE])
  1349.                 Your("hug passes harmlessly through %s.",
  1350.                 mon_nam(mon));
  1351.             else if (!sticks(mon->data))
  1352.                 if (mon==u.ustuck) {
  1353.                 pline("%s is being %s.", Monnam(mon),
  1354.                     u.umonnum==PM_ROPE_GOLEM ? "choked":
  1355.                     "crushed");
  1356.                 sum[i] = damageum(mon, mattk);
  1357.                 } else if(sum[i-1] && sum[i-2]) {
  1358.                 You("grab %s!", mon_nam(mon));
  1359.                 u.ustuck = mon;
  1360.                 sum[i] = damageum(mon, mattk);
  1361.                 }
  1362.             break;
  1363.  
  1364.         case AT_EXPL:    /* automatic hit if next to */
  1365.             dhit = -1;
  1366.             wakeup(mon);
  1367.             sum[i] = explum(mon, mattk);
  1368.             break;
  1369.  
  1370.         case AT_ENGL:
  1371.             if((dhit = (tmp > rnd(20+i)))) {
  1372.                 wakeup(mon);
  1373.                 if (mon->data == &mons[PM_SHADE])
  1374.                     Your("attempt to surround %s is harmless.",
  1375.                     mon_nam(mon));
  1376.                 else
  1377.                     sum[i]= gulpum(mon,mattk);
  1378.             } else
  1379.                 missum(mon, mattk);
  1380.             break;
  1381.  
  1382.         case AT_MAGC:
  1383.             /* No check for uwep; if wielding nothing we want to
  1384.              * do the normal 1-2 points bare hand damage...
  1385.              */
  1386.             if (i==0 && (u.usym==S_KOBOLD
  1387.                 || u.usym==S_ORC
  1388.                 || u.usym==S_GNOME
  1389.                 )) goto use_weapon;
  1390.  
  1391.         case AT_NONE:
  1392.             continue;
  1393.             /* Not break--avoid passive attacks from enemy */
  1394.  
  1395.         case AT_BREA:
  1396.         case AT_SPIT:
  1397.         case AT_GAZE:    /* all done using #monster command */
  1398.             dhit = 0;
  1399.             break;
  1400.  
  1401.         default: /* Strange... */
  1402.             impossible("strange attack of yours (%d)",
  1403.                  mattk->aatyp);
  1404.         }
  1405.         if (dhit == -1)
  1406.         rehumanize();
  1407.         if(sum[i] == 2) return(passive(mon, 1, 0, (mattk->aatyp==AT_KICK)));
  1408.                             /* defender dead */
  1409.         else {
  1410.         (void) passive(mon, sum[i], 1, (mattk->aatyp==AT_KICK));
  1411.         nsum |= sum[i];
  1412.         }
  1413.         if (uasmon == &playermon)
  1414.         break; /* No extra attacks if no longer a monster */
  1415.         if (multi < 0)
  1416.         break; /* If paralyzed while attacking, i.e. floating eye */
  1417.     }
  1418.     return(nsum);
  1419. }
  1420.  
  1421. #endif /* POLYSELF */
  1422.  
  1423. /*    Special (passive) attacks on you by monsters done here.        */
  1424.  
  1425. int
  1426. passive(mon, mhit, malive, kicked)
  1427. register struct monst *mon;
  1428. register boolean mhit;
  1429. register int malive;
  1430. boolean kicked;
  1431. {
  1432.     register struct permonst *ptr = mon->data;
  1433.     register int i, tmp;
  1434.  
  1435.     for(i = 0; ; i++) {
  1436.         if(i >= NATTK) return(malive | mhit);    /* no passive attacks */
  1437.         if(ptr->mattk[i].aatyp == AT_NONE) break;    /* try this one */
  1438.     }
  1439.     /* Note: tmp not always used */
  1440.     if (ptr->mattk[i].damn)
  1441.         tmp = d((int)ptr->mattk[i].damn, (int)ptr->mattk[i].damd);
  1442.     else if(ptr->mattk[i].damd)
  1443.         tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1444.     else
  1445.         tmp = 0;
  1446.  
  1447. /*    These affect you even if they just died */
  1448.  
  1449.     switch(ptr->mattk[i].adtyp) {
  1450.  
  1451.       case AD_ACID:
  1452.         if(mhit && rn2(2)) {
  1453.         if (Blind || !flags.verbose) You("are splashed!");
  1454.         else    You("are splashed by %s acid!", 
  1455.                             s_suffix(mon_nam(mon)));
  1456.  
  1457. #ifdef POLYSELF
  1458.         if(!resists_acid(uasmon))
  1459. #endif
  1460.             mdamageu(mon, tmp);
  1461.         if(!rn2(30)) erode_armor(TRUE);
  1462.         }
  1463.         if(mhit && !rn2(6)) {
  1464.         if (kicked) {
  1465.             if (uarmf)
  1466.             (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE);
  1467.         } else erode_weapon(TRUE);
  1468.         }
  1469.         exercise(A_STR, FALSE);
  1470.         break;
  1471.       case AD_STON:
  1472.         if(mhit)
  1473.           if (!kicked)
  1474.         if (!uwep && !uarmg
  1475. #ifdef POLYSELF
  1476.             && !resists_ston(uasmon)
  1477.             && !(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  1478. #endif
  1479.            ) {
  1480.             You("turn to stone...");
  1481.             done_in_by(mon);
  1482.             return 2;
  1483.         }
  1484.         break;
  1485.       case AD_RUST:
  1486.         if(mhit && !mon->mcan)
  1487.           if (kicked) {
  1488.         if (uarmf)
  1489.             (void) rust_dmg(uarmf, xname(uarmf), 1, TRUE);
  1490.           } else
  1491.         erode_weapon(FALSE);
  1492.         break;
  1493.       case AD_MAGM:
  1494.         /* wrath of gods for attacking Oracle */
  1495.         if(Antimagic) {
  1496.         shieldeff(u.ux, u.uy);
  1497.         pline("A hail of magic missiles narrowly misses you!");
  1498.         } else {
  1499.         You("are hit by magic missiles appearing from thin air!");
  1500.         mdamageu(mon, tmp);
  1501.         }
  1502.         break;
  1503.       default:
  1504.         break;
  1505.     }
  1506.  
  1507. /*    These only affect you if they still live */
  1508.  
  1509.     if(malive && !mon->mcan && rn2(3)) {
  1510.  
  1511.         switch(ptr->mattk[i].adtyp) {
  1512.  
  1513.           case AD_PLYS:
  1514.         if(ptr == &mons[PM_FLOATING_EYE]) {
  1515.             if (!canseemon(mon)) {
  1516.             break;
  1517.             }
  1518.             if(mon->mcansee) {
  1519.             if(Reflecting & W_AMUL) {
  1520.                 makeknown(AMULET_OF_REFLECTION);
  1521.                 pline("%s gaze is reflected by your medallion.",
  1522.                   s_suffix(Monnam(mon)));
  1523.             } else if(Reflecting & W_ARMS) {
  1524.                 makeknown(SHIELD_OF_REFLECTION);
  1525.                 pline("%s gaze is reflected by your shield.",
  1526.                   s_suffix(Monnam(mon)));
  1527.             } else {
  1528.                 You("are frozen by %s gaze!", 
  1529.                   s_suffix(mon_nam(mon)));
  1530.                 nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -120);
  1531.             }
  1532.             } else {
  1533.             pline("%s cannot defend itself.",
  1534.                 Adjmonnam(mon,"blind"));
  1535.             if(!rn2(500)) change_luck(-1);
  1536.             }
  1537.         } else { /* gelatinous cube */
  1538.             You("are frozen by %s!", mon_nam(mon));
  1539.             nomul(-tmp);
  1540.             exercise(A_DEX, FALSE);
  1541.         }
  1542.         break;
  1543.           case AD_COLD:        /* brown mold or blue jelly */
  1544.         if(monnear(mon, u.ux, u.uy)) {
  1545.             if(Cold_resistance) {
  1546.               shieldeff(u.ux, u.uy);
  1547.             You("feel a mild chill.");
  1548. #ifdef POLYSELF
  1549.             ugolemeffects(AD_COLD, tmp);
  1550. #endif
  1551.             break;
  1552.             }
  1553.             You("are suddenly very cold!");
  1554.             mdamageu(mon, tmp);
  1555.         /* monster gets stronger with your heat! */
  1556.             mon->mhp += tmp / 2;
  1557.             if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
  1558.         /* at a certain point, the monster will reproduce! */
  1559.             if(mon->mhpmax > ((int) (mon->m_lev+1) * 8)) {
  1560.             register struct monst *mtmp;
  1561.  
  1562.             if ((mtmp = clone_mon(mon)) != 0) {
  1563.                 mtmp->mhpmax = mon->mhpmax /= 2;
  1564.                 if(!Blind)
  1565.                 pline("%s multiplies from your heat!",
  1566.                                 Monnam(mon));
  1567.             }
  1568.             }
  1569.         }
  1570.         break;
  1571.           case AD_STUN:        /* specifically yellow mold */
  1572.         if(!Stunned)
  1573.             make_stunned((long)tmp, TRUE);
  1574.         break;
  1575.           case AD_FIRE:
  1576.         if(monnear(mon, u.ux, u.uy)) {
  1577.             if(Fire_resistance) {
  1578.             shieldeff(u.ux, u.uy);
  1579.             You("feel mildly warm.");
  1580. #ifdef POLYSELF
  1581.             ugolemeffects(AD_FIRE, tmp);
  1582. #endif
  1583.             break;
  1584.             }
  1585.             You("are suddenly very hot!");
  1586.             mdamageu(mon, tmp);
  1587.         }
  1588.         break;
  1589.           case AD_ELEC:
  1590.         if(Shock_resistance) {
  1591.             shieldeff(u.ux, u.uy);
  1592.             You("feel a mild tingle.");
  1593. #ifdef POLYSELF
  1594.             ugolemeffects(AD_ELEC, tmp);
  1595. #endif
  1596.             break;
  1597.         }
  1598.         You("are jolted with electricity!");
  1599.         mdamageu(mon, tmp);
  1600.         break;
  1601.           default:
  1602.         break;
  1603.         }
  1604.     }
  1605.     return(malive | mhit);
  1606. }
  1607.  
  1608. /* Note: caller must ascertain mtmp is mimicing... */
  1609. void
  1610. stumble_onto_mimic(mtmp)
  1611. register struct monst *mtmp;
  1612. {
  1613.     if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
  1614.         u.ustuck = mtmp;
  1615.     if (Blind) {
  1616.         if(!Telepat)
  1617.         pline("Wait!  That's a monster!");
  1618.     } else if (glyph_is_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
  1619.         (glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_hcdoor ||
  1620.          glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_vcdoor))
  1621.         pline("The door actually was %s!", a_monnam(mtmp));
  1622.     else if (glyph_is_object(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
  1623.         glyph_to_obj(levl[u.ux+u.dx][u.uy+u.dy].glyph) == GOLD_PIECE)
  1624.         pline("That gold was %s!", a_monnam(mtmp));
  1625.     else {
  1626.         pline("Wait!  That's %s!", a_monnam(mtmp));
  1627.     }
  1628.  
  1629.     wakeup(mtmp);    /* clears mimicing */
  1630. }
  1631.  
  1632. static void
  1633. nohandglow(mon)
  1634. struct monst *mon;
  1635. {
  1636.     char *hands=makeplural(body_part(HAND));
  1637.  
  1638.     if (!u.umconf || mon->mconf) return;
  1639.     if (u.umconf == 1) {
  1640.         if (Blind)
  1641.             Your("%s stop tingling.", hands);
  1642.         else
  1643.             Your("%s stop glowing %s.", hands,
  1644.                 Hallucination ? hcolor() : red);
  1645.     } else {
  1646.         if (Blind)
  1647.             pline("The tingling in your %s lessens.", hands);
  1648.         else
  1649.             Your("%s no longer glow so brightly %s.", hands,
  1650.                 Hallucination ? hcolor() : red);
  1651.     }
  1652.     u.umconf--;
  1653. }
  1654.  
  1655. /*uhitm.c*/
  1656.